🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / firmware / src / commonMain / kotlin / org / meshtastic / feature / firmware / FirmwareUpdateViewModel.kt
Displaying Raw • Download
feature/firmware/src/commonMain/kotlin/org/meshtastic/feature/firmware/FirmwareUpdateViewModel.kt 60b7908e1bfeb63eee3dcf6df655da4adb72e6c0 (60b7908e) Text, 20.73 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.firmware
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.coroutines.CancellationException
Tff7b72import T7ee787kotlinx.coroutines.CoroutineStart
Tff7b72import T7ee787kotlinx.coroutines.Job
Tff7b72import T7ee787kotlinx.coroutines.NonCancellable
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.collectLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.filterNotNull
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787kotlinx.coroutines.withContext
Tff7b72import T7ee787kotlinx.coroutines.withTimeoutOrNull
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.di.ApplicationCoroutineScope
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.common.util.safeCatching
Tff7b72import T7ee787org.meshtastic.core.database.entity.FirmwareRelease
Tff7b72import T7ee787org.meshtastic.core.database.entity.FirmwareReleaseType
Tff7b72import T7ee787org.meshtastic.core.datastore.BootloaderWarningDataSource
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.DeviceHardware
Tff7b72import T7ee787org.meshtastic.core.model.MyNodeInfo
Tff7b72import T7ee787org.meshtastic.core.repository.DeviceHardwareRepository
Tff7b72import T7ee787org.meshtastic.core.repository.FirmwareReleaseRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioController
Tff7b72import T7ee787org.meshtastic.core.repository.RadioPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.isBle
Tff7b72import T7ee787org.meshtastic.core.repository.isSerial
Tff7b72import T7ee787org.meshtastic.core.repository.isTcp
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.UiText
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_battery_low
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_copying
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_extracting
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_failed
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_flashing
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_method_ble
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_method_usb
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_method_wifi
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_no_device
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_node_info_missing
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_unknown_error
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_unknown_hardware
Tff7b72import T7ee787org.meshtastic.core.resources.unknown
Tff7b72private Tff7b72const Tff7b72val Te6edf3DEVICE_DETACH_TIMEOUT Tff7b72= T79c0ff3T79c0ff0Te6edf3_000L
Tff7b72private Tff7b72const Tff7b72val Te6edf3VERIFY_TIMEOUT Tff7b72= T79c0ff6T79c0ff0Te6edf3_000L
Tff7b72private Tff7b72const Tff7b72val Te6edf3VERIFY_DELAY Tff7b72= T79c0ff2T79c0ff0T79c0ff0T79c0ff0L
Tff7b72private Tff7b72const Tff7b72val Te6edf3MIN_BATTERY_LEVEL Tff7b72= T79c0ff1T79c0ff0
Tff7b72private Tff7b72const Tff7b72val Te6edf3LOCAL_RELEASE_ID Tff7b72= Ta5d6ff"Ta5d6fflocalTa5d6ff"
Tff7b72private Tff7b72val Te6edf3BLUETOOTH_ADDRESS_REGEX Tff7b72= Te6edf3RegexTb4b4b4(Ta5d6ff"Ta5d6ff([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}Ta5d6ff"Tb4b4b4)
T8b949e/**
* ViewModel driving the firmware update screen. Coordinates release checking, file retrieval, transport-specific update
* execution, and post-update device verification.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tf0883e@KoinViewModel
Tff7b72class T56d364FirmwareUpdateViewModelTb4b4b4(
Tff7b72private Tff7b72val Te6edf3firmwareReleaseRepositoryTb4b4b4: Te6edf3FirmwareReleaseRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3deviceHardwareRepositoryTb4b4b4: Te6edf3DeviceHardwareRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioControllerTb4b4b4: Te6edf3RadioControllerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioPrefsTb4b4b4: Te6edf3RadioPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3bootloaderWarningDataSourceTb4b4b4: Te6edf3BootloaderWarningDataSourceTb4b4b4,
Tff7b72private Tff7b72val Te6edf3firmwareUpdateManagerTb4b4b4: Te6edf3FirmwareUpdateManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3usbManagerTb4b4b4: Te6edf3FirmwareUsbManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3fileHandlerTb4b4b4: Te6edf3FirmwareFileHandlerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3applicationScopeTb4b4b4: Te6edf3ApplicationCoroutineScopeTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3_state Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3IdleTb4b4b4)
Tff7b72val Te6edf3stateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3FirmwareUpdateStateTff7b72> Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3connectionState Tff7b72= Te6edf3radioControllerTb4b4b4.Te6edf3connectionState
Tff7b72private Tff7b72val Te6edf3_selectedReleaseType Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3FirmwareReleaseTypeTb4b4b4.Te6edf3STABLETb4b4b4)
Tff7b72val Te6edf3selectedReleaseTypeTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3FirmwareReleaseTypeTff7b72> Tff7b72= Te6edf3_selectedReleaseTypeTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_selectedRelease Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3FirmwareRelease?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3selectedReleaseTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3FirmwareRelease?Tff7b72> Tff7b72= Te6edf3_selectedReleaseTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_deviceHardware Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3DeviceHardware?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3deviceHardware Tff7b72= Te6edf3_deviceHardwareTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_currentFirmwareVersion Tff7b72= Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3currentFirmwareVersion Tff7b72= Te6edf3_currentFirmwareVersionTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3updateJobTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3tempFirmwareFileTb4b4b4: Te6edf3FirmwareArtifact? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3originalDeviceAddressTb4b4b4: Tffa657String? Tff7b72= Tff7b72null
Tff7b72init Tb4b4b4{
T8b949e// Cleanup potential leftovers
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Te6edf3checkForUpdatesTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonClearedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onClearedTb4b4b4(Tb4b4b4)
T8b949e// viewModelScope is already cancelled when onCleared() runs, so launch cleanup on the
T8b949e// application-wide scope (SupervisorJob + ioDispatcher). ATOMIC start + NonCancellable
T8b949e// context keeps cleanup running even if something tries to cancel it mid-flight.
Te6edf3applicationScopeTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3start Tff7b72= Te6edf3CoroutineStartTb4b4b4.Te6edf3ATOMICTb4b4b4) Tb4b4b4{
Te6edf3withContextTb4b4b4(Te6edf3NonCancellableTb4b4b4) Tb4b4b4{ Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetReleaseTypeTb4b4b4(Te6edf3typeTb4b4b4: Te6edf3FirmwareReleaseTypeTb4b4b4) Tb4b4b4{
Te6edf3_selectedReleaseTypeTb4b4b4.Te6edf3value Tff7b72= Te6edf3type
Te6edf3checkForUpdatesTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffcancelUpdateTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3updateJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Idle
Te6edf3checkForUpdatesTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongMethodTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffcheckForUpdatesTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3updateJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3updateJob Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Checking
Te6edf3safeCatching Tb4b4b4{
Tff7b72val Te6edf3ourNode Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3value
Tff7b72val Te6edf3address Tff7b72= Te6edf3radioPrefsTb4b4b4.Te6edf3devAddrTb4b4b4.Te6edf3valueTff7b72?.Te6edf3dropTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3address Tff7b72=Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3ourNode Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_no_deviceTb4b4b4)Tb4b4b4)
Tff7b72returnTf0883e@launch
Tb4b4b4}
Te6edf3getDeviceHardwareTb4b4b4(Te6edf3ourNodeTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3deviceHardware Tff7b72-Tff7b72>
Te6edf3_deviceHardwareTb4b4b4.Te6edf3value Tff7b72= Te6edf3deviceHardware
Te6edf3_currentFirmwareVersionTb4b4b4.Te6edf3value Tff7b72= Te6edf3ourNodeTb4b4b4.Te6edf3firmwareVersion
Tff7b72val Te6edf3releaseFlow Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3_selectedReleaseTypeTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Te6edf3FirmwareReleaseTypeTb4b4b4.Te6edf3LOCALTb4b4b4) Tb4b4b4{
Te6edf3flowOfTb4b4b4(Tff7b72nullTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3firmwareReleaseRepositoryTb4b4b4.Te6edf3getReleaseFlowTb4b4b4(Te6edf3_selectedReleaseTypeTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
Te6edf3releaseFlowTb4b4b4.Te6edf3collectLatest Tb4b4b4{ Te6edf3release Tff7b72-Tff7b72>
Te6edf3_selectedReleaseTb4b4b4.Te6edf3value Tff7b72= Te6edf3release
Tff7b72val Te6edf3dismissed Tff7b72= Te6edf3bootloaderWarningDataSourceTb4b4b4.Te6edf3isDismissedTb4b4b4(Te6edf3addressTb4b4b4)
Tff7b72val Te6edf3firmwareUpdateMethod Tff7b72=
Tff7b72when Tb4b4b4{
Te6edf3radioPrefsTb4b4b4.Te6edf3isSerialTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tb4b4b4{
T8b949e// Serial OTA is not yet supported for ESP32 — only nRF52/RP2040 UF2.
Tff7b72if Tb4b4b4(Te6edf3deviceHardwareTb4b4b4.Te6edf3isEsp32ArcTb4b4b4) Tb4b4b4{
Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Unknown
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Usb
Tb4b4b4}
Tb4b4b4}
Te6edf3radioPrefsTb4b4b4.Te6edf3isBleTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Ble
Te6edf3radioPrefsTb4b4b4.Te6edf3isTcpTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Wifi
Tff7b72else Tff7b72-Tff7b72> Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Unknown
Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ReadyTb4b4b4(
Te6edf3release Tff7b72= Te6edf3releaseTb4b4b4,
Te6edf3deviceHardware Tff7b72= Te6edf3deviceHardwareTb4b4b4,
Te6edf3address Tff7b72= Te6edf3addressTb4b4b4,
Te6edf3showBootloaderWarning Tff7b72=
Te6edf3deviceHardwareTb4b4b4.Te6edf3requiresBootloaderUpgradeForOta Tff7b72=Tff7b72= Tff7b72true Tff7b72&Tff7b72&
Tff7b72!Te6edf3dismissed Tff7b72&Tff7b72&
Te6edf3radioPrefsTb4b4b4.Te6edf3isBleTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3updateMethod Tff7b72= Te6edf3firmwareUpdateMethodTb4b4b4,
Te6edf3currentFirmwareVersion Tff7b72= Te6edf3ourNodeTb4b4b4.Te6edf3firmwareVersionTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Te6edf3e Tff7b72-Tff7b72>
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffError checking for updatesTa5d6ff" Tb4b4b4}
Tff7b72val Te6edf3unknownError Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_unknown_errorTb4b4b4)
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(
Tff7b72if Tb4b4b4(Te6edf3eTb4b4b4.Te6edf3message Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3UiTextTb4b4b4.Te6edf3DynamicStringTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4) Tff7b72else Te6edf3unknownErrorTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffstartUpdateTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3currentState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72as? Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Ready Tff7b72?: Tff7b72return
Tff7b72val Te6edf3release Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3release Tff7b72?: Tff7b72return
Te6edf3originalDeviceAddress Tff7b72= Te6edf3radioPrefsTb4b4b4.Te6edf3devAddrTb4b4b4.Te6edf3value
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3checkBatteryLevelTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3updateJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3updateJob Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3tempFirmwareFile Tff7b72=
Te6edf3firmwareUpdateManagerTb4b4b4.Te6edf3startUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3releaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3deviceHardwareTb4b4b4,
Te6edf3address Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3addressTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72when Tb4b4b4(Tff7b72val Te6edf3finalState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3valueTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Success Tff7b72-Tff7b72>
Te6edf3verifyUpdateResultTb4b4b4(Te6edf3originalDeviceAddressTb4b4b4, Te6edf3finalStateTb4b4b4.Te6edf3wasLowSpeedTransferTb4b4b4)
Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Error Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
T8b949e// Defense-in-depth: handler returned without setting a terminal state
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffFirmware update returned without terminal state: Tffd700${Te6edf3_stateTb4b4b4.Te6edf3valueTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_failedTb4b4b4)Tb4b4b4)
Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFirmware update cancelled — cause: Tffd700${Te6edf3eTb4b4b4.Te6edf3causeTffd700}Ta5d6ff message: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Idle
Te6edf3checkForUpdatesTb4b4b4(Tb4b4b4)
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFirmware update failedTa5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_failedTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsaveDfuFileTb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3currentState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72as? Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3AwaitingFileSave Tff7b72?: Tff7b72return
Tff7b72val Te6edf3firmwareArtifact Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3uf2Artifact
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ProcessingTb4b4b4(Te6edf3ProgressStateTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_copyingTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3fileHandlerTb4b4b4.Te6edf3copyToUriTb4b4b4(Te6edf3firmwareArtifactTb4b4b4, Te6edf3uriTb4b4b4)
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ProcessingTb4b4b4(Te6edf3ProgressStateTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_flashingTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3withTimeoutOrNullTb4b4b4(Te6edf3DEVICE_DETACH_TIMEOUTTb4b4b4) Tb4b4b4{ Te6edf3usbManagerTb4b4b4.Te6edf3deviceDetachFlowTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72?: Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffTimed out waiting for device to detach, assuming successTa5d6ff" Tb4b4b4}
Te6edf3verifyUpdateResultTb4b4b4(Te6edf3originalDeviceAddressTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffError saving DFU fileTa5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_failedTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffstartUpdateFromFileTb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3currentState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72as? Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Ready Tff7b72?: Tff7b72return
Tff7b72if Tb4b4b4(Te6edf3currentStateTb4b4b4.Te6edf3updateMethod Tff7b72is Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3Ble Tff7b72&Tff7b72& Tff7b72!Te6edf3isValidBluetoothAddressTb4b4b4(Te6edf3currentStateTb4b4b4.Te6edf3addressTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_no_deviceTb4b4b4)Tb4b4b4)
Tff7b72return
Tb4b4b4}
Te6edf3originalDeviceAddress Tff7b72= Te6edf3radioPrefsTb4b4b4.Te6edf3devAddrTb4b4b4.Te6edf3value
Te6edf3updateJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3updateJob Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ProcessingTb4b4b4(
Te6edf3ProgressStateTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_extractingTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3extension Tff7b72= Tff7b72if Tb4b4b4(Te6edf3currentStateTb4b4b4.Te6edf3updateMethod Tff7b72is Te6edf3FirmwareUpdateMethodTb4b4b4.Te6edf3BleTb4b4b4) Ta5d6ff"Ta5d6ff.zipTa5d6ff" Tff7b72else Ta5d6ff"Ta5d6ff.uf2Ta5d6ff"
Tff7b72val Te6edf3extractedFile Tff7b72= Te6edf3fileHandlerTb4b4b4.Te6edf3extractFirmwareTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3currentStateTb4b4b4.Te6edf3deviceHardwareTb4b4b4, Te6edf3extensionTb4b4b4)
Te6edf3tempFirmwareFile Tff7b72= Te6edf3extractedFile
Tff7b72val Te6edf3firmwareUri Tff7b72= Te6edf3extractedFileTff7b72?.Te6edf3uri Tff7b72?: Te6edf3uri
Tff7b72val Te6edf3updateArtifact Tff7b72=
Te6edf3firmwareUpdateManagerTb4b4b4.Te6edf3startUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3FirmwareReleaseTb4b4b4(Te6edf3id Tff7b72= Te6edf3LOCAL_RELEASE_IDTb4b4b4, Te6edf3zipUrl Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3releaseNotes Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3deviceHardwareTb4b4b4,
Te6edf3address Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3addressTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4,
Te6edf3firmwareUri Tff7b72= Te6edf3firmwareUriTb4b4b4,
Tb4b4b4)
Te6edf3tempFirmwareFile Tff7b72= Te6edf3updateArtifact Tff7b72?: Te6edf3extractedFile
Tff7b72when Tb4b4b4(Tff7b72val Te6edf3finalState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3valueTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Success Tff7b72-Tff7b72>
Te6edf3verifyUpdateResultTb4b4b4(Te6edf3originalDeviceAddressTb4b4b4, Te6edf3finalStateTb4b4b4.Te6edf3wasLowSpeedTransferTb4b4b4)
Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Error Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffFirmware update returned without terminal state: Tffd700${Te6edf3_stateTb4b4b4.Te6edf3valueTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_failedTb4b4b4)Tb4b4b4)
Te6edf3tempFirmwareFile Tff7b72= Te6edf3cleanupTemporaryFilesTb4b4b4(Te6edf3fileHandlerTb4b4b4, Te6edf3tempFirmwareFileTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffError starting update from fileTa5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_failedTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffdismissBootloaderWarningForCurrentDeviceTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3currentState Tff7b72= Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72as? Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Ready Tff7b72?: Tff7b72return
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Te6edf3bootloaderWarningDataSourceTb4b4b4.Te6edf3dismissTb4b4b4(Te6edf3currentStateTb4b4b4.Te6edf3addressTb4b4b4)
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3currentStateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3showBootloaderWarning Tff7b72= Tff7b72falseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffverifyUpdateResultTb4b4b4(Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3wasLowSpeedTransferTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4) Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Verifying
T8b949e// Trigger a fresh connection attempt by MeshService using the original prefixed address
Te6edf3addressTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3fullAddr Tff7b72-Tff7b72>
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffPost-update: Requesting MeshService to reconnect to Tffd700$Te6edf3fullAddrTa5d6ff" Tb4b4b4}
Te6edf3radioControllerTb4b4b4.Te6edf3setDeviceAddressTb4b4b4(Te6edf3fullAddrTb4b4b4)
Tb4b4b4}
T8b949e// Wait for device to reconnect and settle
Tff7b72val Te6edf3result Tff7b72=
Te6edf3withTimeoutOrNullTb4b4b4(Te6edf3VERIFY_TIMEOUTTb4b4b4) Tb4b4b4{
T8b949e// Wait for both Connected state and node info to be present
Te6edf3connectionStateTb4b4b4.Te6edf3first Tb4b4b4{ Tffa657it Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected Tb4b4b4}
Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3delayTb4b4b4(Te6edf3VERIFY_DELAYTb4b4b4) T8b949e// Extra buffer for initial config sync
Tff7b72true
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3result Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffPost-update verification timed out for Tffd700$Te6edf3addressTa5d6ff" Tb4b4b4}
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3VerificationFailed
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3SuccessTb4b4b4(Te6edf3wasLowSpeedTransferTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffcheckBatteryLevelTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3node Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3value Tff7b72?: Tff7b72return Tff7b72true
Tff7b72val Te6edf3level Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3batteryLevel Tff7b72?: T79c0ff1
Tff7b72val Te6edf3isBatteryLow Tff7b72= Te6edf3level Tff7b72in T79c0ff1.Tb4b4b4.Te6edf3MIN_BATTERY_LEVEL
Tff7b72if Tb4b4b4(Te6edf3isBatteryLowTb4b4b4) Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_battery_lowTb4b4b4, Te6edf3levelTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72return Tff7b72!Te6edf3isBatteryLow
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffgetDeviceHardwareTb4b4b4(Te6edf3ourNodeTb4b4b4: Te6edf3MyNodeInfoTb4b4b4)Tb4b4b4: Te6edf3DeviceHardware? Tb4b4b4{
Tff7b72val Te6edf3nodeInfo Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3value
Tff7b72val Te6edf3hwModelInt Tff7b72= Te6edf3nodeInfoTff7b72?.Te6edf3userTff7b72?.Te6edf3hw_modelTff7b72?.Te6edf3value
Tff7b72val Te6edf3target Tff7b72= Te6edf3ourNodeTb4b4b4.Te6edf3pioEnv
Tff7b72return Tff7b72if Tb4b4b4(Te6edf3hwModelInt Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3deviceHardwareRepositoryTb4b4b4.Te6edf3getDeviceHardwareByModelTb4b4b4(Te6edf3hwModelIntTb4b4b4, Te6edf3targetTb4b4b4)Tb4b4b4.Te6edf3getOrElse Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_unknown_hardwareTb4b4b4, Te6edf3hwModelIntTb4b4b4)Tb4b4b4)
Tff7b72null
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3_stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_node_info_missingTb4b4b4)Tb4b4b4)
Tff7b72null
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffcleanupTemporaryFilesTb4b4b4(
Te6edf3fileHandlerTb4b4b4: Te6edf3FirmwareFileHandlerTb4b4b4,
Te6edf3tempFirmwareFileTb4b4b4: Te6edf3FirmwareArtifact?Tb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3FirmwareArtifact? Tb4b4b4{
Te6edf3safeCatching Tb4b4b4{
Te6edf3tempFirmwareFileTff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isTemporary Tb4b4b4}Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3fileHandlerTb4b4b4.Te6edf3deleteFileTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Te6edf3fileHandlerTb4b4b4.Te6edf3cleanupAllTemporaryFilesTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Te6edf3e Tff7b72-Tff7b72> Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to cleanup temp filesTa5d6ff" Tb4b4b4} Tb4b4b4}
Tff7b72return Tff7b72null
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffisValidBluetoothAddressTb4b4b4(Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3address Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3BLUETOOTH_ADDRESS_REGEXTb4b4b4.Te6edf3matchesTb4b4b4(Te6edf3addressTb4b4b4)
Tff7b72private Tff7b72fun Te6edf3FirmwareReleaseRepositoryTb4b4b4.Td2a8ffgetReleaseFlowTb4b4b4(Te6edf3typeTb4b4b4: Te6edf3FirmwareReleaseTypeTb4b4b4)Tb4b4b4: Te6edf3FlowTff7b72<Te6edf3FirmwareRelease?Tff7b72> Tff7b72= Tff7b72when Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Te6edf3FirmwareReleaseTypeTb4b4b4.Te6edf3STABLE Tff7b72-Tff7b72> Te6edf3stableRelease
Te6edf3FirmwareReleaseTypeTb4b4b4.Te6edf3ALPHA Tff7b72-Tff7b72> Te6edf3alphaRelease
Te6edf3FirmwareReleaseTypeTb4b4b4.Te6edf3LOCAL Tff7b72-Tff7b72> Te6edf3flowOfTb4b4b4(Tff7b72nullTb4b4b4)
Tb4b4b4}
T8b949e/** The transport mechanism used to deliver firmware to the device, determined by the active radio connection. */
Tff7b72sealed Tff7b72class T56d364FirmwareUpdateMethodTb4b4b4(Tff7b72val Te6edf3descriptionTb4b4b4: Te6edf3StringResourceTb4b4b4) Tb4b4b4{
Tff7b72data Tff7b72object T56d364Usb Tb4b4b4: Te6edf3FirmwareUpdateMethodTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_method_usbTb4b4b4)
Tff7b72data Tff7b72object T56d364Ble Tb4b4b4: Te6edf3FirmwareUpdateMethodTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_method_bleTb4b4b4)
Tff7b72data Tff7b72object T56d364Wifi Tb4b4b4: Te6edf3FirmwareUpdateMethodTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_method_wifiTb4b4b4)
Tff7b72data Tff7b72object T56d364Unknown Tb4b4b4: Te6edf3FirmwareUpdateMethodTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3unknownTb4b4b4)
Tb4b4b4}
Served by rngit 1.4.2 - Generated in 0.12s